import string
import redis
import random
from captcha.image import ImageCaptcha
from django.contrib.auth.hashers import check_password
from django.db.models import Q
from django.http import HttpResponse
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_jwt.utils import jwt_encode_handler, jwt_payload_handler

from user.models import User


#生成图片验证码
class GenerateImageCode(APIView):
    def get(self, request, uuid):   #1 接收前端传来的uuid,图片id

        # 2 使用随机模块生成,字符+数字的随机数,长度自定
        # string.ascii_letters   生成区分大小写的字符
        # string.digits:生成0-9的随机数字
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 4))

        #3 使用captcha模块生成图片
        img = ImageCaptcha()

        #4 把生成的随机数字添加到图片上
        image = img.generate(salt)

        #5 连接redis   (host='localhost', port=6379, db=0可写可不写)
        redis_cli = redis.Redis(host='localhost', port=6379)

        # 6 存储图片验证码，设置过期时间5分钟
        redis_cli.setex(str(uuid), 300, salt)

        #7 返回图片
        return HttpResponse(image, content_type='image/png')


#校验图片验证码"
class CheckImageCode(APIView):
    def get(self, request):
        #1 获取前端传来的验证码信息
        # 查询字符串传参  goods/?page=18&pagesize=20    goods/     request.query_params.get('xxxx')
        image_id = request.query_params.get('imageCodeID')
        image_code = request.query_params.get('imageCode')

        # 2 连接redis 根据前端传来的i mage_id 获取 redis 中的图片验证码
        redis_cli = redis.Redis(host='localhost', port=6379)
        result = redis_cli.get(image_id)     # result : redis里验证码的value值

        if result:  # 数据存在
            # decode()解码 result是redis里取出的验证码  需要解码
            # lower()都转为小写
            if result.decode().lower() != image_code.lower():
                return Response({'msg': '验证码输入错误!'})
            else:
                return Response({'code': 200})
        else:   # 数据不存在
            return Response({'msg': '验证码过期'})


#判断用户名是否重复
class CheckUsername(APIView):
    def get(self, request, username): # 1 固定参数传参  goods/<int:id>/  username获取前端传来的用户名

        #  2 校验数据中是否有此用户名  统计当前用户的数量
        rest = User.objects.filter(username=username).count()
        if rest > 0:    # 说明用户名已经存在
            return Response({'msg': '用户已注册', 'code': 400 })
        return Response({'code': 200})

#判断手机号是否重复
class CheckMobile(APIView):
    def get(self, request, mobile):
        rest = User.objects.filter(mobile=mobile).count()
        if rest > 0:
            return Response({'msg': '手机号已注册','code': 400 })
        return Response({'code': 200})

#注册
class UserRegister(APIView):
    def post(self, request):
        # 1 请求体传参   form,文件  request.data.get() 获取前端中的数据,拿过来和数据中的字段比较
        user_name = request.data.get('userName')
        pwd = request.data.get('pwd')
        mobile = request.data.get('mobile')
        agree = request.data.get('agree')

        # 2 后端要校验前端传来的数据  只要有一个为空就错误
        if not all([user_name, pwd, mobile, agree]):
            return Response({'msg': "请输入完善注册用户信息", "code": 400})

        if not agree:
            # 说明没有同意协议
            return Response({"msg": "请勾选协议"})

        #  3 写入数据库   create_user 密文存储密码
        User.objects.create_user(username=user_name, password=pwd, mobile=mobile)
        return Response({'msg': "注册成功!", "code": 200})

#登录
class UserLogin(APIView):
    def post(self, request):
        #  1 获取前端输入的账号密码
        username1 = request.data.get('user')
        pwd = request.data.get('pwd')

        # 2 校验   不存在      存在  check_password校验密码
        #前端传来的用户名是否在数据库
        try:  # users 用户名一致时的所有账号注册信息
            users = User.objects.get(Q(username=username1) | Q(mobile=username1))  #多方式登录 手机号和账号 Q查询或 |

        except User.DoesNotExist as e:
            return Response({'msg': '用户不存在,先注册', 'code': 400})

        # check_password模块检验密码是否一致  返回的is_correct 结果为布尔值
        is_correct = check_password(pwd, users.password)

        if is_correct: #返回True 说明用户名和密码匹配

            # 此处是生成token
            payload = jwt_payload_handler(users)    #传入第二部分用户信息
            token = jwt_encode_handler(payload)     #根据第二部分生成token

            # # token写入cookie,方便退出  cookie在响应中生成
            # resp = Response({'msg': '登陆成功', 'code': 200, 'user': {'userName': users.username}, 'token': token})
            # # 设置cookie中
            # resp.set_cookie('token', token)
            return Response({'msg': '登陆成功', 'code': 200, 'user': {'userName': users.username}, 'token': token})
        else:
            return Response({'msg': '用户名密码错误', 'code': 400})

#退出
class Logout(APIView):
    def post(self, request):

        # token = request.COOKIE.get('token')
        if request.session.get('username'):
            del request.session['username']
        return Response({'msg': '退出成功', 'code': 200})



